package testing;

import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

import dse.Cluster;
import dse.DataObject;
import dse.DataObjectAccessRanking;
import dse.DseException;
import dse.ExperimentConfiguration;
import dse.Network;
import dse.modules.BloomFilterGenerator;
import dse.modules.GeneralBloomFilterGenerator;
import dse.modules.GeneralDataObjectAccessRanker;
import dse.modules.GeneralDataObjectGenerator;
import dse.modules.GeneralRequestEventScheduler;
import dse.modules.ThresholdCacheDecisionMaker;
import dse.modules.eln.EarthLikeNetwork;
import dse.modules.eln.EarthLikeNetworkClusterGenerator;
import dse.modules.eln.EarthLikeNetworkTopologyGenerator;



/**
 * A TON of the tests are not avaialbe here, but as the main method in the 
 * module classes.
 * 
 * @author Aaron
 */
public class TestHelper {
	
	/** This is a utility class, so no instances are allowed. */
	private TestHelper () {/**/}

	public static ExperimentConfiguration createSystemSettings (
			String [] args, 
			int seedIndex
			) 
	throws DseException
	{
		System.out.println("Creating system settings object...");
		Properties p = new Properties();
		p.put("period-length", "1");
		if (args.length > seedIndex)
			p.put("seed", args[seedIndex]);
		p.put("periods-to-run", "500");
		return new ExperimentConfiguration (p);
	}
	
	public static EarthLikeNetworkTopologyGenerator createELNTopologyGenerator (
			ExperimentConfiguration ss,
			String [] args,
			int nodesIndex,
			int polesIndex,
			int pullIndex
			) 
	throws DseException
	{
		System.out.println("Creating topology generator...");
		EarthLikeNetworkTopologyGenerator eng = 
			new EarthLikeNetworkTopologyGenerator ();
		Hashtable<String, String> props = new Hashtable<String, String>();		
		if (nodesIndex != -1 && nodesIndex < args.length)
			props.put("nodes", args[nodesIndex]);
		if (polesIndex != -1 && polesIndex < args.length)
			props.put("poles", args[polesIndex]);
		if (pullIndex != -1 && pullIndex < args.length)
			props.put("min-pull", args[pullIndex]);
		eng.initalize(ss, props);
		return eng;
	}

	public static EarthLikeNetwork createELNetwork (
			ExperimentConfiguration ss,
			String [] args,
			int nodesIndex,
			int polesIndex,
			int pullIndex
			) 
	throws DseException
	{
		EarthLikeNetworkTopologyGenerator eng = 
			createELNTopologyGenerator(
					ss, args, nodesIndex, polesIndex, pullIndex
					);
		System.out.println("Creating network...");
		return (EarthLikeNetwork)eng.createNetwork();
	}
	
	public static EarthLikeNetworkClusterGenerator createELNClusterGenerator (
			ExperimentConfiguration ss,
			String [] args,
			int maxSizeIndex,
			int neighborhoodSizeIndex
			)
	throws DseException
	{
		System.out.println("Creating cluster generator...");
		EarthLikeNetworkClusterGenerator elncg = 
			new EarthLikeNetworkClusterGenerator ();
		Hashtable<String, String> props = new Hashtable<String, String>();
		if (maxSizeIndex != -1 && maxSizeIndex < args.length)
			props.put("max-size", args[maxSizeIndex]);
		else
			props.put("max-size", "200");
		
		if (neighborhoodSizeIndex != -1 && neighborhoodSizeIndex < args.length)
			props.put("neighborhood-size", args[neighborhoodSizeIndex]);
		else
			props.put("neighborhood-size", "8");
		
		
		elncg.initalize(ss, props);
		return elncg;
	}
	
	public static void createClusters (
			ExperimentConfiguration ss,
			String [] args,
			int maxSizeIndex,
			Network network
			)
	throws DseException
	{
		EarthLikeNetworkClusterGenerator elncg = 
			createELNClusterGenerator(ss, args, maxSizeIndex, -1);
		
		System.out.println("Creating clusters...");
		elncg.generateClusters(network);
		System.out.println("Cluster count: " + network.clusterCount());
	}
	
	public static GeneralDataObjectGenerator createDataObjectGenerator (
			ExperimentConfiguration ss,
			String [] args,
			int numberOfObjectsIndex,
			int minSizeIndex,
			int maxSizeIndex,
			int shareCountIndex,
			int reqShareCountIndex
			)
	throws DseException
	{
		System.out.println("Creating data object generator...");
		
		GeneralDataObjectGenerator gdog = new GeneralDataObjectGenerator ();

		Hashtable<String, String> props = new Hashtable<String, String>();
		
		if (numberOfObjectsIndex != -1 && numberOfObjectsIndex < args.length)
			props.put("num-objects", args[numberOfObjectsIndex]);
		if (minSizeIndex != -1 && minSizeIndex < args.length)
			props.put("min-size", args[minSizeIndex]);
		else
			props.put("min-size", "1000");
		if (maxSizeIndex != -1 && maxSizeIndex < args.length)
			props.put("max-size", args[maxSizeIndex]);
		else
			props.put("max-size", "1000000");
		if (shareCountIndex != -1 && shareCountIndex < args.length)
			props.put("share-count", args[shareCountIndex]);		
		else
			props.put("share-count", "10");
		if (reqShareCountIndex != -1 && reqShareCountIndex < args.length)
			props.put("req-share-count", args[reqShareCountIndex]);
		else
			props.put("req-share-count", "5");
		
		gdog.initalize(ss, props);
		return gdog;
	}
	
	public static Vector<DataObject> createDataObjects (
			ExperimentConfiguration ss,
			String [] args,
			int numberOfObjectsIndex,
			int minSizeIndex,
			int maxSizeIndex,
			int shareCountIndex,
			int reqShareCountIndex
			)
	throws DseException
	{
		GeneralDataObjectGenerator gdog = 
			createDataObjectGenerator(
					ss, args, numberOfObjectsIndex, minSizeIndex, 
					maxSizeIndex, shareCountIndex, reqShareCountIndex
					);
		
		System.out.println("Creating data objects...");
		Vector<DataObject> dos = gdog.generateDataObjects();
		System.out.println("Data object count: " + dos.size());
		return dos;
	}

	public static GeneralDataObjectAccessRanker createDataObjectAccessRanker (
			ExperimentConfiguration ss,
			String [] args,
			int diffIndex
			)
	throws DseException
	{
		System.out.println("Creating data object access ranker...");
		
		GeneralDataObjectAccessRanker a = new GeneralDataObjectAccessRanker ();

		Hashtable<String, String> props = new Hashtable<String, String>();
		
		if (diffIndex != -1 && diffIndex < args.length)
			props.put("diff", args[diffIndex]);
		else 
			props.put("diff", "200");
		
		a.initalize(ss, props);
		
		return a;
	}
		
	
	public static Map<Cluster, DataObjectAccessRanking> 
		generateDataObjectAccessRankings (
				ExperimentConfiguration ss,
				String [] args,
				int diffIndex,
				Network network,
				Vector<DataObject> dataObjects
				)
	throws DseException
	{
		GeneralDataObjectAccessRanker a = createDataObjectAccessRanker(
				ss, args, diffIndex
				);
		
		System.out.println("Creating data object generator...");
		return a.generateAccessRankings(network, dataObjects);
	}
	
	
	public static GeneralRequestEventScheduler createScheduler (
			ExperimentConfiguration ss,
			String [] args,
			int requestFrequencyIndex,
			int zipfCardinalityIndex
			)
	throws DseException 
	{
		GeneralRequestEventScheduler scheduler = 
			new GeneralRequestEventScheduler ();
		
		Hashtable<String, String> props = new Hashtable<String, String>();
		
		if (requestFrequencyIndex != -1 && requestFrequencyIndex < args.length)
			props.put("request-frequency", args[requestFrequencyIndex]);
		if (zipfCardinalityIndex != -1 && zipfCardinalityIndex < args.length)
			props.put("zipf-dist-cardinality", args[zipfCardinalityIndex]);
		
		scheduler.initalize(ss, props);
		
		return scheduler; 
	}
	
	
	public static ThresholdCacheDecisionMaker createCacheDecisionMaker (
			ExperimentConfiguration ss,
			String [] args,
			int periodsToAnalyzeIndex,
			int thresholdIndex
			)
	throws DseException 
	{
		ThresholdCacheDecisionMaker dm = 
			new ThresholdCacheDecisionMaker ();
		
		Hashtable<String, String> props = new Hashtable<String, String>();
		
		if (periodsToAnalyzeIndex != -1 && periodsToAnalyzeIndex < args.length)
			props.put("periods-to-analyze", args[periodsToAnalyzeIndex]);
		if (thresholdIndex != -1 && thresholdIndex < args.length)
			props.put("threshold", args[thresholdIndex]);
		
		dm.initalize(ss, props);
		
		return dm; 
	}
	
	public static BloomFilterGenerator createBloomFilterGenerator (
			ExperimentConfiguration ss
			)
	throws DseException
	{
		GeneralBloomFilterGenerator bf = new GeneralBloomFilterGenerator ();
		
		Hashtable<String, String> props = new Hashtable<String, String>();
		
		props.put("m", "256");
		props.put("hashes-per-object", "6");
		
		bf.initalize(ss, props);
		
		return bf;
	}
}
